﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lidgren.Network;
using System.Threading;

namespace NetworkedGameServer
{
    public enum Headers
    {
        Login,
        WorldData,
        PlayerData
    }

    class Program
    {
        static NetServer Server;
        static NetPeerConfiguration Config;

        static void Main(string[] args)
        {
            Config = new NetPeerConfiguration("NetworkedGame");
            Config.Port = 7777;
            Config.MaximumConnections = 200;
            Config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
            Server = new NetServer(Config);
            Server.Start();
            Console.WriteLine("Server Started");
            List<Player> Players = new List<Player>();
            NetIncomingMessage inc;
            DateTime time = DateTime.Now;
            TimeSpan timetopass = new TimeSpan(0, 0, 0, 0, 5);
            Console.WriteLine("Waiting for new connections and updating world state to current ones");

            while (true)
            {
                if ((inc = Server.ReadMessage()) != null)
                {
                    switch (inc.MessageType)
                    {
                        case NetIncomingMessageType.ConnectionApproval:

                            // Read the first byte of the packet
                            // ( Enums can be casted to bytes, so it be used to make bytes human readable )
                            if (inc.ReadByte() == (byte)Headers.Login)
                            {
                                Console.WriteLine("Incoming LOGIN");
                                inc.SenderConnection.Approve();
                            }

                            break;

                        case NetIncomingMessageType.Data:

                            if (inc.ReadByte() == (byte)Headers.PlayerData)
                            {
                                NetConnection connection = inc.SenderConnection;

                                foreach (Player player in Players)
                                {
                                    if (player.Connection == connection)
                                    {
                                        player.PosX = inc.ReadFloat();
                                        break;
                                    }
                                }
                            }
                            break;
                        case NetIncomingMessageType.StatusChanged:
                            
                            Console.WriteLine(inc.SenderConnection.ToString() + " status changed. " + (NetConnectionStatus)inc.SenderConnection.Status);
                            if (inc.SenderConnection.Status == NetConnectionStatus.Disconnected || inc.SenderConnection.Status == NetConnectionStatus.Disconnecting)
                            {
                                foreach (Player player in Players)
                                {
                                    if (player.Connection == inc.SenderConnection)
                                    {
                                        Players.Remove(player);
                                        break;
                                    }
                                }
                            }
                            else if(inc.SenderConnection.Status == NetConnectionStatus.Connected)
                            {
                                Players.Add(new Player(15.0f, inc.SenderConnection));
                                NetOutgoingMessage outmsg = Server.CreateMessage();
                                outmsg.Write((byte)Headers.WorldData);
                                outmsg.Write(Players.Count);

                                foreach (Player player in Players)
                                {
                                    outmsg.WriteAllProperties(player, System.Reflection.BindingFlags.Public);
                                }
                                
                                Server.SendMessage(outmsg, inc.SenderConnection, NetDeliveryMethod.UnreliableSequenced, 0);
                                Console.WriteLine("Approved new connection and updated the world status");
                            }
                            break;
                    }

                    Server.Recycle(inc);
                } 

                /*if ((time + timetopass) < DateTime.Now)
                {
                    if (Server.ConnectionsCount != 0)
                    {
                        NetOutgoingMessage outmsg = Server.CreateMessage();
                        outmsg.Write((byte)Headers.WorldData);
                        outmsg.Write(Players.Count);

                        foreach (Player player in Players)
                        {
                            outmsg.WriteAllProperties(player, System.Reflection.BindingFlags.Public);
                        }

                        Server.SendMessage(outmsg, Server.Connections, NetDeliveryMethod.UnreliableSequenced, 0);
                    }

                    time = DateTime.Now;
                }*/
                 

                System.Threading.Thread.Sleep(1);
            }
        }
    }
}
